package codejam;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;

import cjcast.y2015.problem.LEDPrinter;

/**
 * This code was copied from the Internet, not mine.
 * 
 * Variables Dictionary:
 * 
 * DigitCount - Number of Sequential Digits.
 */
@SuppressWarnings({
        "PMD.DataflowAnomalyAnalysis",
        "PMD.SystemPrintln" })
public final class SevenSegmentDisplay {

    /** */
    static final byte[] SEGMENT = {
            0X7E, //1111110 0 126
            0X30, //0110000 1 48
            0X6D, //1101101 2 109
            0X79, //1111001 3 121
            0X33, //0110011 4 51
            0X5B, //1011011 5 91
            0X5F, //1011111 6 95
            0X70, //1110000 7 112
            0X7F, //1111111 8 127
            0X7B }; //1111011 123


    /** */
    public static final byte FIRST_FLAG_OFF = 0X7F;

    /** Segment Combination Count. */
    public static final int SEG_COMB_COUNT = SEGMENT.length;

    /** */
    public static final int DIGIT_SEQ_MAX = 100;

    /** */
    public static final int DIGIT_LEN = 7;

    /** */
    private SevenSegmentDisplay() {}


    /**
     * @param args unused.
     * @throws IOException fatal error when fired.
     */
    public static void main(final String[] args) throws IOException
    {
        solveSevensegmentDisplay();
    }

    /**
     * @throws IOException fatal error when fired.
     */
    public static void solveSevensegmentDisplay() throws IOException
    {
        final File file = new File("C:\\SevensegmentDisplay.large.in");

        final BufferedReader buffReader = new BufferedReader(new FileReader(
            file));

        final BufferedWriter buffWriter = new BufferedWriter(new FileWriter(
            "C:\\SevensegmentDisplay.large.correct.out"));

        final int total = Integer.parseInt(buffReader.readLine());


        for (int caseIdx = 1; caseIdx <= total; caseIdx++) {
            final String[] strArr = buffReader.readLine().split(" ");
            final int digitCount = Integer.parseInt(strArr[0]);
            int resultCurr = 0;
            int resultPrev = 0;
            final byte[] history = buildHistory(strArr, digitCount);

            byte unsure = 0x00;
            boolean matched = false;

            for (int segmentIdx = 0; segmentIdx < SEG_COMB_COUNT; segmentIdx++) {

                byte broken = 0;
                byte good = 0;
                boolean fail = false;

                for (int historyIdx = 0; historyIdx < digitCount
                        && historyIdx < SEG_COMB_COUNT; historyIdx++) {
                    good |= history[historyIdx];

                    final int nextToTest = (segmentIdx - historyIdx + SEG_COMB_COUNT)
                            % SEG_COMB_COUNT;

                    System.out.println("Guaranteed Good");
                    LEDPrinter.print(good);

                    final byte digitOnTrial = SEGMENT[nextToTest];

                    System.out.println("Digit on Trial(" + "Assumed start: "
                            + segmentIdx + ", historyIdx=" + historyIdx
                            + ", To Test: " + nextToTest + "):");
                    LEDPrinter.print(digitOnTrial);


                    broken |= digitOnTrial & ~history[historyIdx];

                    System.out.println("Broken = Digit on Trial & ~Current");
                    LEDPrinter.print(
                        broken,
                        digitOnTrial,
                        (byte) ~history[historyIdx]);
                    unsure = (byte) (~good & ~broken & FIRST_FLAG_OFF);
                    System.out.println("Unsure = ~good & ~broken");
                    LEDPrinter.print(unsure, (byte) ~good, (byte) ~broken);


                    final boolean nonZeroGoodBroke = (good & broken) != 0;
                    System.out.println("Try1: Good And Broken non-zero: "
                            + nonZeroGoodBroke);
                    LEDPrinter.print(good, broken);

                    final boolean nonZeroHistBlah = (history[historyIdx] & (byte) ~(digitOnTrial & good)) != 0;
                    System.out
                        .println("Try2: history[i] & ~(digitOnTrial & good) non-zero: "
                                + nonZeroHistBlah);
                    LEDPrinter
                        .print(
                            history[historyIdx],
                            digitOnTrial,
                            good,
                            (byte) ~(digitOnTrial & good),
                            (byte) (history[historyIdx] & (byte) ~(digitOnTrial & good)));

                    if (nonZeroGoodBroke || nonZeroHistBlah) {
                        System.out.println("Failed.");
                        fail = true;
                        break;
                    }

                }

                if (!fail) {
                    resultCurr = SEGMENT[(segmentIdx - digitCount
                            % SEG_COMB_COUNT + SEG_COMB_COUNT)
                            % SEG_COMB_COUNT]
                            & ~broken;
                    LEDPrinter.print((byte) resultCurr);

                    if ((resultCurr & unsure) != 0 || matched
                            && resultPrev != resultCurr) {
                        matched = false;
                        break;
                    } else {
                        matched = true;
                        resultPrev = resultCurr;
                    }
                }
            }

            printOutput(buffWriter, caseIdx, resultCurr, matched);
        }
        buffReader.close();
        buffWriter.close();
    }


    private static byte[] buildHistory(final String[] strArr,
            final int digitCount)
    {
        System.out.println("Given: ");
        final byte[] history = new byte[DIGIT_SEQ_MAX];
        for (int i = 1; i <= digitCount; i++) {
            history[i - 1] = Byte.parseByte(strArr[i], 2);
        }
        System.out.println();
        LEDPrinter.print(Arrays.copyOfRange(strArr, 1, strArr.length));
        return history;
    }

    private static void printOutput(final BufferedWriter buffWriter,
            final int caseIdx, final int result, final boolean matched)
            throws IOException
    {
        String output;
        if (matched) {

            final String binString = String.format(
                "%7s",
                Integer.toBinaryString(result)).replace(' ', '0');

            output = "Case #" + caseIdx + ": " + binString + "\n";
        } else {
            output = "Case #" + caseIdx + ": ERROR!\n";
        }
        System.out.println(output);
        buffWriter.write(output);

    }

    @SuppressWarnings("PMD.OnlyOneReturn" /* Two only. */)
    static int boolAsInt(final boolean bool)
    {
        if (bool) {
            return 1;
        } else {
            return 0;
        }
    }

}
